﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bll;
using Common;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Model;
using StackExchange.Redis;
using Web.Controllers.Util;
using Web.Filter;
using Web.Redis;
using Web.Security;
using Web.Util;

namespace Web.Controllers.Stu
{
    [Route("api/stu/")]
    [ApiController]
    [Authorize]
    [QueryFilter]
    public class DefaultController : MyBaseController<Object>
    {
        public IClockLogBll clockLogBll { get; set; }
        public IUsualScoreBll usualScoreBll { get; set; }
        public IUsualScoreLogBll usualScoreLogBll { get; set; }
        public IUsualScoreItemBll usualScoreItemBll { get; set; }
        // public IClaimsAccessor MyUser { get; set; }
        /// <summary>
        /// 签到打卡
        /// </summary>
        /// <param name="answer">签到答案</param>
        /// <param name="clockId">如果存在，则表示补签到打卡，否则表示在正常时间段打卡</param>
        /// <returns>{Status:true,Code:200成功|500失败|501未开始|502已打卡,Msg:""}</returns>
        //[HttpPost("clock")]
        //[HttpGet("clock/{answer}")]
        //HttpPost和HttpGet不能同时加在方法上。同时支持get和post请求http://blog.sina.com.cn/s/blog_78106bb10102va8m.html
        [AcceptVerbs("get","post")]
        [Route("clock")]
        public Result Clock(string answer, int? clockId=null)
        {
           
            string classid = MyUser.Project;//班级id
            string name = MyUser.Name;
            MyRedisHelper rd = MyRedisHelper.Instance();
            rd.SetSysCustomKey("clock_stu");//已签到的学生集合     
            RedisValue expire = rd.StringGet(classid + "expire");//签到时长
            if (expire.IsNullOrEmpty)
            {
                if (clockId != null)//补签，放到if (expire.IsNullOrEmpty)里面是为了保证补签是在正式签到之后，因为正式签到完成后会进行旷课平时成绩计入，补签会把旷课的分加回来，然后减去迟到的分
                {
                    //签到日志
                    var clockLog = clockLogBll.SelectOne(o => o.ClockId == clockId && o.StudentId == MyUser.Id);
                    if (clockLog != null)
                    {
                        //判断当前补签的时间是否是在当前课程上课时间段
                        //获取当前系统时间并判断是否为服务时间
                        TimeSpan nowDt = DateTime.Now.TimeOfDay;
                        TimeSpan workStartDT = clockLog.Clock.From_time.TimeOfDay;
                        TimeSpan workEndDT = clockLog.Clock.To_time.TimeOfDay;
                        if (nowDt<=workStartDT||nowDt>=workEndDT)
                        {
                            return Result.Success($"补签失败，不在时间{clockLog.Clock.From_time.ToShortTimeString()}-{clockLog.Clock.To_time.ToShortTimeString()}范围内");
                        }

                        clockLog.Status = Model.ClockLog.ClockStatus.late;
                        clockLogBll.Update(clockLog);//修改
                    }
                    //记录平时成绩迟到
                    SchoolConfig schoolConfig = EntityCacheHelper.GetInstance().GetSchoolConfig(MyUser.SchoolId.GetValueOrDefault());
                    if (schoolConfig != null && schoolConfig.LateId > 0)//配置项存在 且配置了旷课关联的平时表现成绩项 才计入到平时表现成绩
                    {
                        //查找平时成绩
                        UsualScore usualScore = usualScoreBll.SelectOne(o => o.StudentId == MyUser.Id && o.CourseId == clockLog.Clock.CourseId);
                        //查找平时成绩项
                        UsualScoreItem usualScoreItem = usualScoreItemBll.SelectOne(schoolConfig.LateId.GetValueOrDefault());//迟到平时成绩项
                        UsualScoreItem absenceUsualScoreItem = usualScoreItemBll.SelectOne(schoolConfig.AbsenceId.GetValueOrDefault());//旷课平时成绩项
                        if (usualScore == null || usualScoreItem == null|| absenceUsualScoreItem==null)
                        {
                            NLogHelper.logger.Info($"补签失败！学生编号{MyUser.Id}计入平时表现成绩失败,未找到该学生对应{clockLog.Clock.CourseId}课程的平时表现成绩");
                            return Result.Error($"补签失败！学生编号{MyUser.Id}计入平时表现成绩失败,未找到该学生对应{clockLog.Clock.CourseId}课程的平时表现成绩");
                        }
                        //先把旷课的成绩加回来，防止重复扣分
                        usualScore.Score += -absenceUsualScoreItem.Value;//旷课是扣分 ，负数
                        usualScore.Score += usualScoreItem.Value; //减去迟到的分数 。迟到是扣分，负数
                        //开启事务
                        usualScoreBll.DbContext().Database.BeginTransaction();
                        bool ret = usualScoreBll.Update(usualScore);//修改平时成绩
                        UsualScoreLog log = new UsualScoreLog() { SchoolId = MyUser.SchoolId == 0 ? null : MyUser.SchoolId, ScoreId = usualScore.Id, Name = usualScoreItem.Name, Value = usualScoreItem.Value, Sys = false };
                        usualScoreLogBll.Add(log);//添加平时成绩记录
                        usualScoreBll.DbContext().Database.CommitTransaction();//结束事务

                    }
                    return Result.Success("补签成功");
                }
                return Result.Error("亲，签到未开始或已经结束了哦").SetCode(501);
            }
            //正式签到
            if (!rd.SortedSetContains(classid, name))
            {//包含表示打卡过
                var rightanswer = rd.StringGet<string>(classid + "answer");//签到答案
                if (rightanswer != answer)
                {
                    return Result.Error("打卡失败，暗号错误");
                }
                rd.SortedSetAdd<string>(classid, name, DateTime.Now.ToOADate());
                long clocknum = rd.SortedSetLength(classid);//班级签到数量
                                                            //消息通知
                ImHelper.SendChanMessage("student-" + MyUser.Id, "clockclass-" + classid, ImMsg.Msg("clockclass-" + classid, new { clocknum = clocknum }, new Sender() { ClientId = "student-" + MyUser.Id }));
                return Result.Success("打卡成功");
            }
            return Result.Error("已打卡").SetCode(502);

        }
        /// <summary>
        /// 获取学生签到的教师id，即找谁签到 
        /// </summary>
        /// <returns></returns>
        [HttpPost("getclockteacher")]
        //[HttpGet()]
        public Result GetClockTeacher()
        {
            string classid = MyUser.Project;//班级id          
            MyRedisHelper rd = MyRedisHelper.Instance();
            rd.SetSysCustomKey("clock_stu");//已签到的学生集合      
            string teacherid = rd.StringGet(classid + "teacher");//签到时长
            return Result.Success().SetData(teacherid);
        }
        /// <summary>
        /// 学生签到日志
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        [HttpGet("clocklog")]
        public Result ClockLog([FromQuery] Dictionary<string, string> where)
        {
            // return Result.Success().SetData(clockLogBll.Query().
            // Where(o => o.StudentId == MyUser.Id).AsEnumerable().OrderByDescending(o=>o.Added_time));
            where.Add("StudentId", MyUser.Id.ToString());
            //where.Add("sort", "-Added_time");//排序
            var query = clockLogBll.Query(where);
            query.Items = query.Items.Select(o => new Model.ClockLog() { Added_time = o.Added_time, Clock = o.Clock, Status = o.Status, Student = o.Student });//{Added_time=o.Added_time.Date, Clock=o.Clock, Status=o.Status , Student =o.Student});
            return Result.Success("succeed").SetData(query);
        }
    }
}